part of flutter_project_tool;

void updateIosInfo(ArgResults options, Map<String, dynamic> config) {
  updateInfoPlist(config);
  updateEntitlements(config);
  updateProjectFile(options, config);
}

void updateEntitlements(Map<String, dynamic> config) {
  final file = File(_kIosEntitlementsPath);
  final stringValue = file.readAsStringSync();
  final document = XmlDocument.parse(stringValue);
  final dict = document.getElement('plist')?.getElement('dict');
  if (dict == null) {
    throw Exception('plist dict element not found');
  }
  var elementFound = true;
  final domains = dict.children.whereType<XmlElement>().firstWhere((element) {
    return (element.text == 'com.apple.developer.associated-domains');
  }, orElse: () {
    final builder = XmlBuilder();
    builder.element('key', nest: () {
      builder.text('com.apple.developer.associated-domains');
    });
    dict.children.add(builder.buildFragment());
    elementFound = false;
    return XmlElement(XmlName(''));
  });
  if (elementFound) {
    var index = dict.children.indexOf(domains);
    var domainsValue = dict.children[index + 1].following
        .firstWhere((element) => element.nodeType == XmlNodeType.ELEMENT);
    final applinks =
        'applinks:${config['universal_link_host']}/${config['url_scheme']}';
    domainsValue.children.removeWhere((e) =>
        e.innerText.startsWith('applinks:${config['universal_link_host']}'));
    domainsValue.children
        .add(XmlElement(XmlName('string'))..innerText = applinks);
    file.writeAsStringSync(document.toXmlString(pretty: true, indent: '    '));
    print('ios 更新entitlements完成');
  }
}

void updateProjectFile(ArgResults options, Map<String, dynamic> config) {
  bool isInit = options['init'] != null;
  final file = File(_kIosProjectFilePath);
  String version = config['ios']['version'];
  version = version.replaceAll('.', '');
  version =
      version.substring(0, 1) + '.' + version.substring(1, version.length);
  version =
      version.substring(0, 3) + '.' + version.substring(3, version.length);
  var stringValue = file
      .readAsStringSync()
      .replaceAll(
        RegExp('PRODUCT_BUNDLE_IDENTIFIER.*;'),
        'PRODUCT_BUNDLE_IDENTIFIER = \'${config['ios']['bundle_id']}\';',
      )
      .replaceAll(
        RegExp('MARKETING_VERSION.*;'),
        'MARKETING_VERSION = \'$version\';',
      );
  if (isInit) {
    stringValue = stringValue.replaceAll(
      RegExp('DEVELOPMENT_TEAM.*;'),
      '',
    );
  }
  file.writeAsStringSync(stringValue);
  print('ios 更新projectfile完成');
}

void updateInfoPlist(Map<String, dynamic> config) {
  final file = File(_kIosInfoPlistPath);
  final stringValue = file.readAsStringSync();
  final document = XmlDocument.parse(stringValue);
  final dict = document.getElement('plist')?.getElement('dict');
  if (dict == null) {
    throw Exception('plist dict element not found');
  }
  updateDisplayName(config, dict);
  updateUrlTypes(config, dict);
  file.writeAsStringSync(document.toXmlString(pretty: true, indent: '    '));
  print('ios 更新info.plist完成');
}

void updateDisplayName(Map<String, dynamic> config, XmlElement dict) {
  print('---------------iOS----------------');
  print('显示名：${config['ios']['name']}');
  print('版本号：${config['ios']['version']}');
  print('----------------------------------');
  var elementFound = true;
  final displayName =
      dict.children.whereType<XmlElement>().firstWhere((element) {
    return (element.text == 'CFBundleDisplayName');
  }, orElse: () {
    final builder = XmlBuilder();
    builder.element('key', nest: () {
      builder.text('CFBundleDisplayName');
    });
    dict.children.add(builder.buildFragment());
    dict.children.add(
        XmlElement(XmlName('string'), [], [XmlText(config['ios']['name'])]));
    elementFound = false;
    return XmlElement(XmlName(''));
  });

  if (elementFound) {
    var index = dict.children.indexOf(displayName);
    var displayNameValue = dict.children[index + 1].following
        .firstWhere((element) => element.nodeType == XmlNodeType.ELEMENT);
    displayNameValue.replace(
        XmlElement(XmlName('string'), [], [XmlText(config['ios']['name'])]));
  }
}

void updateUrlTypes(Map<String, dynamic> config, XmlElement dict) {
  final urlTypes = dict.children.whereType<XmlElement>().firstWhere((element) {
    return (element.text == 'CFBundleURLTypes');
  }, orElse: () {
    final builder = XmlBuilder();
    builder.element('key', nest: () {
      builder.text('CFBundleURLTypes');
    });
    dict.children.add(builder.buildFragment());
    dict.children.add(XmlElement(XmlName('array'), [], [], false));
    return XmlElement(XmlName(''));
  });

  final index = dict.children.indexOf(urlTypes);
  final arrayElement = dict.children[index + 1].following.first;
  String qqAppId = config['qq_app_id'];
  var qqAppIdHex = int.parse(qqAppId).toRadixString(16).toUpperCase();
  while (qqAppIdHex.length < 8) {
    qqAppIdHex = '0' + qqAppIdHex;
  }
  updateUrlType('weixin', config['wx_app_id'], arrayElement);
  updateUrlType('alipay', config['url_scheme'], arrayElement);
  updateUrlType('tencent', 'tencent$qqAppId', arrayElement);
  updateUrlType('QQ', 'QQ$qqAppIdHex', arrayElement);
  updateUrlType('scheme', config['url_scheme'], arrayElement);
}

void updateUrlType(String key, String value, XmlNode element) {
  final index = element.children.indexWhere((e) {
    if (e.nodeType == XmlNodeType.ELEMENT) {
      final index = e.children.indexWhere((e1) => e1.text == key);
      return index != -1;
    }
    return false;
  });
  final xmlValue = '''
  <key>CFBundleTypeRole</key>
  <string>Editor</string>
  <key>CFBundleURLName</key>
  <string>$key</string>
  <key>CFBundleURLSchemes</key>
  <array>
    <string>$value</string>
  </array>
          ''';
  if (index != -1) {
    element.children[index].innerXml = xmlValue;
  } else {
    final node = XmlElement(XmlName('dict'))..innerXml = xmlValue;
    element.children.add(node);
  }
}
